package org.bing.engine.common.graniteds;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;

import org.bing.engine.common.logging.Log;
import org.bing.engine.common.logging.LogFactory;
import org.granite.config.flex.ServicesConfig;


public class ServicesConfigBuilder {
    private static final Log logger = LogFactory.getLog(ServicesConfigBuilder.class);

    private static List<String> customServiceConfig = new ArrayList<String>();

    public static boolean addServiceConfig(String id, String source) {
        String item = "<destination id=\"" + id + "\">";
        item += "<properties><factory>monitorFactory</factory><source>" + source + "</source>";
        item += "</properties></destination>";
        customServiceConfig.add(item);
        return true;
    }

    public static ServicesConfig build(ServletContext context, String config) {
        logger.info("Use " + config + " init services config.");
        try {
            return doBuild(context, config);
        } catch (Exception e) {
            logger.error("Fail to build ServicesConfig, return null!", e);
            return null;
        }
    }

    private static InputStream doInput(String res) throws IOException {
        InputStream ins = ServicesConfigBuilder.class.getResourceAsStream(res);
        try {
            String line = null;
            StringBuilder sb = new StringBuilder(4096);
            BufferedReader br = new BufferedReader(new InputStreamReader(ins));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            int pos = sb.lastIndexOf("</service>");
            for (String cfg : customServiceConfig) {
                sb.insert(pos, cfg);
            }
            // logger.info("GDS config is \n" + sb.toString());
            return new ByteArrayInputStream(sb.toString().getBytes());
        } finally {
            try {
                ins.close();
            } catch (IOException e) {
                logger.error("Close resource " + ins + " error!", e);
                ins = null;
            }
        }
    }

    private static ServicesConfig doBuild(ServletContext context, String res) throws Exception {
        logger.info("Build ServicesConfig from " + res);
        ObjectReflectHelper refHelper = ObjectReflectHelper.instance(ServicesConfig.class);
        InputStream ins = doInput(res);
        Object result = refHelper.invoke(null, "loadConfig", new Class[] { InputStream.class }, new Object[] { ins });
        return (ServicesConfig) result;
    }

    public static void main(String[] args) {
        ServicesConfig config = ServicesConfigBuilder.build(null, "/META-INF/services-watcher-config.xml");
        System.out.println(config);
    }
}
